define(function(require) {
  const _ = require('lodash')

  function quadraticBezier(p0, cp, p1, t) {
    const k = 1 - t;
    return k * k * p0 + 2 * ( 1 - t ) * t * cp + t * t * p1;
  }

  /**
   * QBTEqu(QBTEquation) 二阶贝塞尔曲线关于t的方程
   * 将二阶贝塞尔曲线转成关于t的一元二次方程式
   * (p0+p2-2p1)t^2 - 2p0t + p0-pt = 0
   */
  function QBTEquB24ac(p0, p1, p2, pt) {
    return 4 * ((p1 - p0) * (p1 - p0) - (p0 + p2 - 2 * p1) * (p0 - pt));
  }

  /**
   * QBTEquation 求解
   * b24ac b^2-4ab 起名字也是够了，主要是反正上面要算，这里图方便
   */
  function QBTEquSolution(p0, p1, p2, pt, b24ac) {
    let solutions = [];
    const _b = -(p1 - p0) * (p1 - p0);
    const sqrtB24ac = Math.sqrt(b24ac);
    const _2a = 2 * (p0 + p2 - 2 * p1);

    const solution1 = (_b - sqrtB24ac) / _2a;
    if (solution1 >= 0 && solution1 <= 1) {
      solutions.push(solution1)
    }

    const solution2 = (_b + sqrtB24ac) / _2a;
    if (solution2 >= 0 && solution2 <= 1) {
      solutions.push(solution2)
    }
    return solutions;
  }

  function getCurvePointsByX(x, points, scale) {
    const p = points
    const xB24ac = QBTEquB24ac(p[0][0], p[1][0], p[2][0], x);
    const retPoints = []
    if (xB24ac > 0) {
      const xts = QBTEquSolution(p[0][0], p[1][0], p[2][0], x, xB24ac);
      for (let i = 0; i < xts.length; i++) {
        const t = xts[i];
        const x = quadraticBezier(p[0][0], p[1][0], p[2][0], t);
        const y = quadraticBezier(p[0][1], p[1][1], p[2][1], t);
        retPoints.push([x, y])
      }
    }
    return retPoints
  }

  /**
   * @param p0 [x, y]
   * @param cp 一致
   * @param p1
   * @returns {{get: get}}
   */
  function bezierAnimation(points, PFP = 2) {
    let t = 0;
    const interval = 0.1; //由于是非线性

    return {
      get: function() {
        t += PFP / 400;
        if (t > 1) {
          t = 0;
        }
        //t 是一个位置，然后要找到整条作用域上和t等间隔的所有位置
        let tArr = findAll(0, 1, t, interval);
        return _.map(tArr, function(it) {
          const x = quadraticBezier(points[0][0], points[1][0], points[2][0], it);
          const y = quadraticBezier(points[0][1], points[1][1], points[2][1], it);
          return [x, y]
        })
      }
    }

  }

  function findAll(p0, p1, p, interval) {
    let all = []
    for (let i = 0; i < parseInt((p - p0) / interval); i++) {
      all.push(p - (i + 1) * interval);
    }
    all.push(p);

    for (let i = 0; i < parseInt((p1 - p) / interval); i++) {
      all.push(p + (i + 1) * interval)
    }
    return all;
  }

  return { quadraticBezier, bezierAnimation, QBTEquB24ac, QBTEquSolution, getCurvePointsByX }
})
